MOOC Utils

Utils like auto assignment solver extension and course notice announcment notification for MOOC courses

Notification system

Introduction#

Storing and listing notifications, tying them to users and subscriptions, and tracking read state. Channels exist in the model; async delivery and retries are still ahead.

Project structure#

The notification system resides in the notice-reminders package under app/. The structure relevant to notifications includes:

  • Models: define the data schema for notifications, channels, users, and subscriptions
  • Services: encapsulate business logic for creating notifications and managing channels
  • API Routers: expose endpoints for listing notifications and marking them as read
  • Schemas: define serialization models for API responses

Core components#

  • Notification model: stores notification records linked to a user, subscription, optional channel, and timestamp; tracks read/unread state
  • NotificationChannel model: stores per-user channels (e.g., email, Telegram) with address and activation flag
  • NotificationService: creates notifications and manages listing and read-state updates
  • NotificationChannelService: lists, creates, and disables notification channels for a user
  • API endpoints: expose listing notifications for a user and marking a notification as read

Key capabilities:

  • Multi-channel support via NotificationChannel
  • Delivery status tracking via is_read flag
  • User-scoped access control enforced in API

Architecture overview#

The notification architecture splits into:

  • API layer: FastAPI routers handle requests and delegate to services
  • Service layer: NotificationService and NotificationChannelService encapsulate business logic
  • Persistence layer: Tortoise ORM models persist notifications and channels
  • Access control: Authentication decorator keeps only authorized users access their notifications

Detailed component analysis#

Notification model and relationships#

The Notification model links to User, Subscription, and optionally NotificationChannel. It captures when a notification was sent and whether it has been read. This design enables:

  • Per-user delivery logs
  • Association with specific course announcements via Subscription
  • Optional channel attribution for delivery tracking

NotificationService implementation#

Responsibilities:

  • Create notifications linking a subscription and announcement to a user and optional channel
  • List all notifications for a user ordered by sent_at descending
  • Mark a notification as read after validating ownership

NotificationChannelService implementation#

Responsibilities:

  • List channels for a user
  • Create a channel with deduplication via unique constraint
  • Disable a channel by setting is_active to false

API endpoints for notifications#

Endpoints:

  • GET /notifications: List notifications for the authenticated user
  • GET /notifications/users/{user_id}: List notifications for a specific user (owner-only)
  • PATCH /notifications/{notification_id}/read: Mark a notification as read (owner-only)

Access control:

  • require_auth decorator enforces authentication
  • Ownership checks ensure users can only access their own notifications

Channel management endpoints#

While the notification endpoints focus on listing and read-state updates, channel management is supported via NotificationChannelService. The service provides:

  • Listing channels for a user
  • Creating channels with deduplication
  • Disabling channels

Note: Dedicated API endpoints for channel management are not present in the current code. Channel operations are handled programmatically via the service layer.

Real-Time alerts and scheduling#

Current implementation:

  • Notifications are created upon event occurrence (e.g., new announcements)
  • No explicit scheduler or queue workers are implemented
  • Real-time delivery is not implemented; delivery is triggered synchronously during creation

Recommendations for later changes:

  • Introduce a task queue (e.g., Celery) to offload channel delivery
  • Add retry logic with exponential backoff for transient failures
  • Implement rate limiting per channel/address
  • Add webhook or push notification hooks for real-time delivery

Templates and personalization#

Current implementation:

  • Notification creation is straightforward and does not include templating
  • Personalization is minimal (only user association)

Recommendations for later changes:

  • Add template engine (e.g., Jinja2) to render subject/body per channel
  • Support dynamic placeholders (user name, course name, date)
  • Allow per-user customization of notification preferences

Dependency analysis#

Notification layers:

  • API depends on services for business logic
  • Services depend on models for persistence
  • Models define relationships and constraints
  • Schemas define API serialization contracts

Performance considerations#

  • Indexing: Ensure foreign keys and frequently queried fields (e.g., user_id, sent_at) are indexed
  • Pagination: For large notification histories, implement pagination in list endpoints
  • Caching: Cache recent notifications per user for read-heavy workloads
  • Batch operations: When scaling to multiple channels, batch deliveries and avoid N+1 queries
  • Asynchronous delivery: Offload channel delivery to background tasks to prevent blocking API requests

Troubleshooting guide#

Common issues and resolutions:

  • Access denied when listing notifications for another user:

  • Cause: Ownership check fails

  • Resolution: Ensure the authenticated user matches the requested user_id

  • Reference: notifications.py

  • Notification not found when marking as read:

  • Cause: Invalid notification_id or wrong user

  • Resolution: Verify notification exists and belongs to the authenticated user

  • Reference: notifications.py

  • Duplicate channel entries:

  • Cause: Unique constraint violation on (user, channel, address)

  • Resolution: Use service create method which handles duplicates; or query existing channel

  • Reference: notification_channel.py, notification_channel_service.py

  • Channel disabled:

  • Cause: is_active is False

  • Resolution: Re-enable the channel via disable/enable operations

  • Reference: notification_channel_service.py

Conclusion#

Records and read state are solid. Async send, retries, and templates are the next real work if you need multi-channel delivery.

Appendices#

API endpoints summary#

  • GET /notifications

  • Description: List notifications for the authenticated user

  • Response: Array of NotificationResponse

  • Reference: notifications.py

  • GET /notifications/users/{user_id}

  • Description: List notifications for a specific user (owner-only)

  • Response: Array of NotificationResponse

  • Reference: notifications.py

  • PATCH /notifications/{notification_id}/read

  • Description: Mark a notification as read (owner-only)

  • Response: NotificationResponse

  • Reference: notifications.py

Notification workflow example#

  • A new announcement triggers creation of a Notification linked to the user’s Subscription
  • Optionally, associate a NotificationChannel to track delivery
  • Users can list notifications and mark them as read via the API

Channel configuration example#

  • Create a channel for a user with a specific channel type and address
  • Channels are unique per user, channel type, and address
  • Disable a channel to stop delivery without deleting it